package com.qf.controller;

import com.qf.annotation.RequiresPermissionsDesc;
import com.qf.service.GoodsProductService;
import com.qf.service.GoodsService;
import com.qf.service.OrderService;
import com.qf.service.UserService;
import com.qf.util.ResponseUtil;
import com.qf.vo.*;
import io.swagger.annotations.Api;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

/**
 * 首页
 * @author mkr
 * @version V1.0
 * @Project java2203-mkr
 * @Package com.qf.controller
 * @Description:
 * @Date 2022/6/17 20:16
 */
@RestController
@RequestMapping("/dashboard")
@Api(value = "首页：用户数量、商品数量、订单数量、金额")
//解决前后端跨域访问问题
@CrossOrigin("*")
public class IndexController {

    @Autowired
    private UserService userService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsProductService productService;
    @Autowired
    private OrderService orderService;

    /**
     * 首页数据统计：
     *  User用户数、SPU商品数量、SKU货品数量、Order订单数
     * @return
     */
    @GetMapping("")
    //具有管理员、商品模块、查询权限才可以访问
    @RequiresPermissions("admin:goods:list")
    //具有系统管理、或者商品管理、订单查询权限，才可以访问
    @RequiresPermissionsDesc(menu = {"系统管理","商品管理","订单管理"},button = "查询")
    public Object dashboard(){
        //1、统计用户数量
        int userCount = userService.countUser();

        //2、统计商品数量
        int goodsCount = goodsService.countGoods();

        //3、统计货品数量
        int productCount = productService.countGoodsProduct();

        //4、统计订单数量
        int orderCount = orderService.countOrder();

        //5、将统计的数据封装到map中，返回
        Map<String , Object> data = new HashMap<>();
        data.put("userTotal", userCount);
        data.put("goodsTotal",goodsCount);
        data.put("productTotal",productCount);
        data.put("orderTotal",orderCount);

        return ResponseUtil.ok(data);
    }

    /**
     * 统计首页需要的图标数据
     * @return
     */
    @RequestMapping("/chart")
    public Object chart(){

        //1、统计最近多少天内的用户增长量
        List<DayStatis> userCount = userService.incrCount();

        //2、统计最近多少天内的订单增长量和当前订单总金额
        List<DayStatis> goodsCount = orderService.incrCount();

        //3、按照商品分类统计订单金额
        List<CategorySellAmts> categoryCount = orderService.categoryCount();
        CategorySellVo categorySellVo = fetchCategorySell(categoryCount);

        //4、合并两个统计结果中的日期数据
        String[] dayData = unionDayData(userCount,goodsCount);
        //转换并合并统计数据，需要合并日期、用户数据、订单数据
        UserOrderCntVo userOrderCntVo = new UserOrderCntVo();
        //用户数据,合并日期和用户数据统计结果
        userOrderCntVo.setUserCnt(fetchArrayCat(dayData, userCount));
        //订单数据，合并日期和订单数据统计结果
        userOrderCntVo.setOrderCnt(fetchArrayCat(dayData, goodsCount));
        //日期数据
        userOrderCntVo.setDayData(dayData);

        //转换统计结果为前端需要的日期、订单数量、订单金额数据
        OrderAmtsVo orderAmtsVo = fetchOrderAmtVo(goodsCount);

        //4、封装到map中
        Map<String , Object> data = new HashMap<>();
        data.put("categorySell",categorySellVo);
        data.put("orderAmts",orderAmtsVo);
        data.put("userOrderCnt",userOrderCntVo);

        return ResponseUtil.ok(data);
    }

    /**
     * 统计封装订单的销售额和订单数量数据
     * @param orderCuts
     * @return
     */
    private OrderAmtsVo fetchOrderAmtVo(List<DayStatis> orderCuts){
        OrderAmtsVo vo = new OrderAmtsVo();

        int size = 0;
        if (orderCuts != null && orderCuts.size()>0){
            size = orderCuts.size();
        }
        //用来存日期数据
        String[] dayData = new String[size];
        //存储订单数据
        int[] orderData = new int[size];
        //存储金额数据
        BigDecimal[] moneyData = new BigDecimal[size];
        //遍历统计的集合数据、获取日期、订单量、订单金额数据
        for(int i = 0 ; i < size ; i++){
            dayData[i] = orderCuts.get(i).getDayStr();
            orderData[i] = orderCuts.get(i).getCnts();
            moneyData[i] = orderCuts.get(i).getAmts();
        }
        vo.setDayData(dayData);
        vo.setOrderCntData(orderData);
        vo.setOrderAmtData(moneyData);
        return vo;
    }

    /**
     * 统计集合中获取的订单数量、如果对应的日期没有统计的数据、则设置为0
     * @param dayData
     * @param dayStatisCnts
     * @return
     */
    private int[] fetchArrayCat(String[] dayData , List<DayStatis> dayStatisCnts){
        //设置存放
        int[] arrCnts = new int[dayData.length];
        //遍历日期数组
        for (int i = 0 ; i < dayData.length ; i++){
            //订单量默认为0
            int daycnt = 0;
            //当前循环出现的日期字符串
            String DayStr = dayData[i];
            //遍历日期和订单统计的聚合数据
            for (DayStatis dayStatisCnt : dayStatisCnts){
                if (DayStr.equals(dayStatisCnt.getDayStr())){
                    //如果数组中的日期和集合中的日期对应，那么拿出对应的统计的订单量数据，
                    //赋值给上面声明的全局数组
                    daycnt = dayStatisCnt.getCnts();
                    //跳出循环
                    break;
                }
            }
            arrCnts[i] = daycnt;
        }
        return arrCnts;
    }

    /**
     * 补全日期数据
     * @param goodsCount
     * @return
     */
    private String[]
    unionDayData(List<DayStatis> userCount , List<DayStatis> goodsCount){
        Set<String> days = new HashSet<>();
        for(DayStatis dayStatis : userCount){
            days.add(dayStatis.getDayStr());
        }
        for(DayStatis dayStatis : goodsCount){
            days.add(dayStatis.getDayStr());
        }
        //将set中的日期数据过滤重复后，放入list集合中
        List<String> list = new ArrayList<>(days);
        //对日期排序
        Collections.sort(list);
        //将list集合转换成数组返回
        return list.toArray(new String[0]);
    }

    /**
     * 封装前端需要的根据分类统计销售额实体类数据
     * @param categoryCount
     * @return
     */
    private CategorySellVo fetchCategorySell(List<CategorySellAmts> categoryCount){
        CategorySellVo vo = new CategorySellVo();

        if (categoryCount == null || categoryCount.size()==0){
            return vo;
        }

        String[] categoryNameArray = new String[categoryCount.size()];
        if ( categoryCount != null ){
            for (int i = 0 ; i < categoryCount.size() ; i++){
                //获取分类名字、并赋值给分类名字数组
                categoryNameArray[i] = categoryCount.get(i).getName();
            }
        }

        //分类名字数组
        vo.setCategoryNames(categoryNameArray);

        //分类名字和统计金额数据
        vo.setCategorySellData(categoryCount);
        return vo;
    }

}
